package gateway

import (
	"com.cyt.common/library/util/httputil"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/frame/g"
	"com.cyt.common/library/util/uuid"
	"github.com/gogf/gf/encoding/gurl"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"time"
)

type Aliyun struct {
	*Gateway
}

const (
	ENDPOINT_URL = "http://dysmsapi.aliyuncs.com"
	ENDPOINT_METHOD = "SendSms"
	ENDPOINT_VERSION = "2017-05-25"
	ENDPOINT_FORMAT = "JSON"
	ENDPOINT_REGION_ID = "cn-hangzhou"
	ENDPOINT_SIGNATURE_METHOD = "HMAC-SHA1"
	ENDPOINT_SIGNATURE_VERSION = "1.0"
)

func (s *Aliyun) New(gateway *Gateway) (Channel, error) {
	return &Aliyun{
		Gateway: gateway,
	}, nil
}

func (s *Aliyun) Send() map[string]interface{} {
	data := s.Message.GetData()

	var number, signName string
	if data["sign_name"] != nil {
		signName = gconv.String(data["sign_name"])
	} else {
		signName = g.Cfg().GetString("sms.gateways.aliyun.sign_name")
	}

	if s.To.GetIDDCode() == "" {
		number = s.To.GetZeroPrefixedNumber()
	} else {
		number = s.To.GetNumber()
	}

	params := g.Map{
		"RegionId": ENDPOINT_REGION_ID,
		"AccessKeyId": g.Cfg().GetString("sms.gateways.aliyun.access_key_id"),
		"Format": ENDPOINT_FORMAT,
		"SignatureMethod": ENDPOINT_SIGNATURE_METHOD,
		"SignatureVersion": ENDPOINT_SIGNATURE_VERSION,
		"SignatureNonce": uuid.GetUUID(),
		"Timestamp": time.Now().UTC().Format(time.RFC3339),
		"Action": ENDPOINT_METHOD,
		"Version": ENDPOINT_VERSION,
		"PhoneNumbers": number,
		"SignName": signName,
		"TemplateCode": s.Message.GetTemplate(),
		"TemplateParam": gconv.String(g.Map{"code": 6379}),
	}

	params["Signature"] = s.GenerateSign(params)
	response := Get(ENDPOINT_URL, params, g.MapStrStr{})
	result := gconv.Map(response)
	if gconv.String(result["Code"]) != "OK" {
		panic(result)
	}

	return result
}

func (s *Aliyun) GenerateSign(params map[string]interface{}) string {
	accessKeySecret := g.Cfg().GetString("sms.gateways.aliyun.access_key_secret")
	urlStr := gurl.Encode(httputil.BuildMapSort(params))
	stringToSign := "GET&%2F&" + urlStr

	mac := hmac.New(sha1.New, []byte(accessKeySecret + "&"))
	mac.Write([]byte(stringToSign))
	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}